﻿
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;

namespace StateManager
{
    public partial class SManager
    {

        public static string ClearJsonComment(string json)
        {
            //注释形式： //一行注释
            Regex Regex = new Regex("\\n[\\s\\t]+//[^\\r]*");
            return Regex.Replace(json, "");
        }

        /// <summary>
        /// 以反射方式执行指定方法
        /// </summary>
        /// <param name="name"></param>
        /// <param name="obj"></param>
        /// <param name="paras"></param>
        /// <returns></returns>
        public object InvokeMethod(string name, object obj, object[] paras)
        {
            return obj.GetType().InvokeMember(name, BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, null, obj, paras);
        }

        /// <summary>
        /// log2file(模块，内容，是否界面操作)，如果未定义则使用内置loger
        /// </summary>
        event Action<string, string, bool> _logFun;
        bool _log2file;
        /// <summary>
        /// 写日志到指定文件夹
        /// </summary>
        /// <param name="node">模块名</param>
        /// <param name="text">日志内容</param>
        /// <param name="manualMode">是否手动执行</param>
        internal void Log(string node, string text, bool manualMode = false)
        {
            if (_logFun != null)
            {
                _logFun(node, text, manualMode);
            }
            if (_log2file)
            {
                LogDir(node, text, manualMode);
            }
        }
        static object _loglock = new object();
        public void LogDir(string node, string text, bool manualMode = false)
        {
            lock (_loglock)
            {
                string fileName = string.Format("log\\{0}\\{0} {1}.log", node, DateTime.Now.ToString("yyyy-MM-dd"));
                string line = string.Format("{0}\t{1}\t{2}\t{3}", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff"), node, manualMode ? "[手动]" : "", text);
                fileName = Path.Combine(ProjectDir, fileName);
                string dir = Path.GetDirectoryName(fileName);
                if (!Directory.Exists(dir))
                    Directory.CreateDirectory(dir);
                System.IO.File.AppendAllLines(fileName, new string[] { line });
            }
        }
        internal void SystemLog(string Text, bool ManualMode = false)
        {
            Log("系统日志", Text, ManualMode);
        }

        ///// <summary>
        ///// 打开指定文件
        ///// </summary>
        ///// <param name="SubDir">默认为程序所在目录</param>
        //public static void OpenFile(string FileName = "")
        //{
        //    //打开指定Windows目录
        //    //System.Diagnostics.Process.Start("Explorer", Path.Combine(AppDomain.CurrentDomain.BaseDirectory, SubDir));
        //    System.Diagnostics.Process.Start(FileName);
        //}

        /// <summary>
        /// 绝对路径转相对
        /// </summary>
        /// <param name="filespec"></param>
        /// <param name="folder"></param>
        /// <returns></returns>
        public static string GetRelativePath(string filespec, string folder)
        {
            string directorySeparatorChar = Path.DirectorySeparatorChar.ToString(); //"\\";
            Uri pathUri = new Uri(filespec);

            if (!folder.EndsWith(directorySeparatorChar))
            {
                folder += directorySeparatorChar;
            }
            Uri folderUri = new Uri(folder);
            return Uri.UnescapeDataString(folderUri.MakeRelativeUri(pathUri).ToString().Replace("/", directorySeparatorChar));
        }

        /// <summary>
        /// 使用NET自带功能转换JSON到OBJECT
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="jsonString"></param>
        /// <returns></returns>
        public static T JsonToObject<T>(string jsonString, IEnumerable<Type> knownTypes = null)
        {
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
            {
                DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings();
                settings.KnownTypes = knownTypes;
                settings.UseSimpleDictionaryFormat = true;
                object obj = new DataContractJsonSerializer(typeof(T), settings).ReadObject(ms);
                return (T)obj;
            }
        }
        public static object JsonToObject(Type type, string jsonString, IEnumerable<Type> knownTypes = null)
        {
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)))
            {
                DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings();
                settings.KnownTypes = knownTypes;
                settings.UseSimpleDictionaryFormat = true;
                object obj = new DataContractJsonSerializer(type, settings).ReadObject(ms);
                return obj;
            }
        }
        /// <summary>
        /// 使用NET自带功能转换为JSON
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string JsonFromObj(object obj, Type type, IEnumerable<Type> knownTypes = null)
        {
            //JsonReaderWriterFactory.CreateJsonReader JsonReaderWriterFactory = new JsonReaderWriterFactory();
            using (var ms = new MemoryStream())
            {
                DataContractJsonSerializerSettings settings = new DataContractJsonSerializerSettings();
                settings.KnownTypes = knownTypes;
                settings.UseSimpleDictionaryFormat = true;
                new DataContractJsonSerializer(type, settings).WriteObject(ms, obj);
                return Encoding.UTF8.GetString(ms.ToArray());
            }
        }
        public static void MapDataMembers<T1, T2>(T1 fromObj, T2 toObj)
        {
            Type t1 = typeof(T1);
            Type t2 = typeof(T1);
            foreach (var p1 in t1.GetFields(BindingFlags.Instance | BindingFlags.Public))
            {
                var attr = Attribute.GetCustomAttribute(p1, typeof(DataMemberAttribute));
                if (attr != null)
                {
                    //读T1值
                    object v = p1.GetValue(fromObj);
                    //写T2值
                    var p2 = t2.GetFields().FirstOrDefault(pp => pp.Name == p1.Name);
                    if (p2 != null)
                    {
                        p2.SetValue(toObj, v);
                    }
                }
            }
            foreach (var p1 in t1.GetProperties(BindingFlags.Instance | BindingFlags.Public))
            {
                var attr = Attribute.GetCustomAttribute(p1, typeof(DataMemberAttribute));
                if (attr != null)
                {
                    //读T1值
                    object v = p1.GetValue(fromObj);
                    //写T2值
                    var p2 = t2.GetProperties().FirstOrDefault(pp => pp.Name == p1.Name);
                    if (p2 != null)
                    {
                        p2.SetValue(toObj, v);
                    }
                }
            }
        }

        /// <summary>
        /// 获得状态机详细信息
        /// </summary>
        /// <returns></returns>
        public string GetThreadsInfo()
        {
            int maxCount, portCount, portCount1, availableCount;
            ThreadPool.GetMaxThreads(out maxCount, out portCount);
            ThreadPool.GetAvailableThreads(out availableCount, out portCount1);
            return string.Format("线程池最大线程数：{0}  可用：{1}", maxCount, availableCount);
        }
        #region 获取实例关联对象，用于高频访问 (取消，因为Json转Object要用[{key:xxx, value:xxx}]麻烦，直接在各实例类加成员变量吧)
        //foreach (var si in cfg.SInfos)
        //{
        //    if (si.links != null)
        //    {
        //        JObject jo = (JObject)si.JObject["Link"];

        //        IDictionary<string, object> dic = si.Link;

        //        foreach (JProperty jp in jo.Properties())
        //        {
        //            object obj = GetSObject(jp.Value.ToString());
        //            if (obj != null)
        //            {
        //                dic[jp.Name] = obj;
        //            }
        //        }
        //    }
        //}
        #endregion
    }

}

